use once_cell::sync::OnceCell;
use sqlx::{MySqlPool, mysql::MySqlPoolOptions};
use std::time::Duration;

/// 全局数据库连接池实例
///
/// 使用 `OnceCell` 确保线程安全的单例初始化，避免重复创建连接池。
/// 在整个应用程序生命周期中共享同一个连接池实例。
static DB_POOL: OnceCell<MySqlPool> = OnceCell::new();

/// 初始化全局数据库连接池
///
/// 该函数用于在应用程序启动时初始化 MySQL 数据库连接池，
/// 配置连接池参数并建立与数据库的连接。
///
/// # 参数
/// - `database_url`: MySQL 数据库连接字符串，格式为：
///   `mysql://username:password@hostname:port/database_name`
///
/// # 返回值
/// - `Ok(())`: 连接池初始化成功
/// - `Err(sqlx::Error)`: 初始化失败，包含具体的数据库错误信息
///
/// # 连接池配置
/// - **最大连接数**: 10 - 控制同时活跃的最大连接数量
/// - **最小连接数**: 1 - 保持的最小空闲连接数，提高响应速度
/// - **空闲超时**: 30秒 - 空闲连接超过此时长会被自动关闭
/// - **获取超时**: 10秒 - 等待获取连接的最大时间
/// - **连接健康检查**: 启用 - 在获取连接前进行 ping 测试，确保连接可用
///
/// # 示例
/// ```no_run
/// use common_service::db_helper::{init_pool, try_get_pool};
///
/// #[tokio::main]
/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
///     // 初始化连接池
///     init_pool("mysql://root:1234@192.168.88.100:31306/app").await?;
///
///     // 使用连接池执行查询 - 使用 try_get_pool() 并处理 Option
///     let pool = try_get_pool()
///         .ok_or("数据库连接池未初始化")?;
///     let row: (i64,) = sqlx::query_as("SELECT ?")
///         .bind(150_i64)
///         .fetch_one(pool)
///         .await?;
///     assert_eq!(row.0, 150);
///     Ok(())
/// }
/// ```
///
/// # 注意事项
/// - 此函数在整个应用程序中只能调用一次
/// - 必须在任何尝试获取连接的操作之前调用
/// - 建议在应用程序启动时立即初始化
/// - 如果初始化失败，应用程序应该终止或采取相应措施
///
/// # 错误处理
/// 可能出现的错误包括：
/// - 数据库连接字符串格式错误
/// - 网络连接失败
/// - 认证失败
/// - 数据库不存在或无权限访问
pub async fn init_pool(database_url: &str) -> Result<(), sqlx::Error> {
    let pool = MySqlPoolOptions::new()
        .max_connections(10) // 最大连接数限制，防止过载
        .min_connections(1) // 最小保持连接数，减少连接建立开销
        .idle_timeout(Duration::from_secs(30)) // 空闲连接超时，释放资源
        .acquire_timeout(Duration::from_secs(10)) // 获取连接超时，避免长时间阻塞
        .test_before_acquire(true) // ✅ 关键配置：获取前健康检查，避免使用失效连接
        .connect(database_url)
        .await?;

    // 设置全局连接池实例，如果重复设置会 panic
    DB_POOL.set(pool).expect("数据库池初始化只能执行一次");
    Ok(())
}

/// 尝试获取数据库连接池（无 panic 版本）
///
/// 安全地获取连接池引用，如果未初始化则返回 `None`。
///
/// # 返回值
/// - `Some(&MySqlPool)`: 连接池已初始化
/// - `None`: 连接池未初始化
///
/// # 示例
/// ```no_run
/// use common_service::db_helper::try_get_pool;
///
/// async fn safe_db_operation() -> Result<(), String> {
///     if let Some(pool) = try_get_pool() {
///         // 执行数据库操作
///         Ok(())
///     } else {
///         Err("数据库未初始化".to_string())
///     }
/// }
/// ```
pub fn try_get_pool() -> Option<&'static MySqlPool> {
    DB_POOL.get()
}
